/**********************************************************************************
Copyright (C), by AppleCai
Project                      : Study Kernel
Description                  : BSP level for MPU6500
CPU and Compiler             : AM335x,ARM-LINIX-GCC
|----------------------------------------------------------------------------------
|               R E V I S I O N   H I S T O R Y
|----------------------------------------------------------------------------------
| Date        Version  Author   Description
| --------    -------  ------   ---------------------------------------------------
| 2020-12-14  1.0.0    AppleCai MPU6500_001: Initial release version
**********************************************************************************/
#if 0 // DTS
spi0_pins: pinmux_spi0_pins {
	pinctrl-single,pins = <
		AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK,PIN_INPUT, MUX_MODE0)		/* SPI0_SCLK */
		AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE0)		/* SPI0_D0 */
		AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_OUTPUT, MUX_MODE0)	/* SPI0_D1 */
		AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_OUTPUT, MUX_MODE0)	/* SPI0_CS0 */
	>;
};


&spi0 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&spi0_pins>;

	apple_MPU6500spi@0 {
		compatible ="applecai,apple6500spi";//"rohm,dh2228fv";
		reg = <0>;
		spi-cpol;
		spi-cpha;
		spi-max-frequency = <100000>;
		spi-tx-bus-width=<1>;
		spi-rx-bus-width=<1>;
	};
};
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/spi/spi.h>
#include <linux/input-polldev.h>
#include <linux/of_device.h>
#include "apple6500.h"
/* spi */
#define APPLE6500_CMD_MULTB	(1 << 6)
#define APPLE6500_CMD_READ	(1 << 7)
#define APPLE6500_WRITECMD(reg)	(reg & 0x7F)
#define APPLE6500_READCMD(reg)	(APPLE6500_CMD_READ | (reg & 0x7F))

static int apple6500_read_spi(struct device *dev, unsigned off)
{
	struct spi_device *spi = to_spi_device(dev);
	unsigned char cmd;
	int ret;
	
	cmd = APPLE6500_READCMD(off);
	ret=spi_w8r8(spi, cmd);
	
	return ret;
}

static int apple6500_write_spi(struct device *dev, unsigned off, unsigned char v)
{
	struct spi_device *spi = to_spi_device(dev);
	unsigned char buf[2];

	buf[0] = APPLE6500_WRITECMD(off);
	buf[1] = v;

	return spi_write(spi, buf, sizeof(buf));
}

static int apple6500_read_block_spi(struct device *dev, unsigned off,unsigned char *buf, size_t size)
{
	struct spi_device *spi = to_spi_device(dev);
	ssize_t status;

	off = APPLE6500_READCMD(off);
	status = spi_write_then_read(spi, &off, 1, buf, size);

	return (status < 0) ? status : 0;
}
static const struct apple6500_transfer_func apple6500_tf_spi = {
	.write = apple6500_write_spi,
	.read = apple6500_read_spi,
	.readblock = apple6500_read_block_spi,
};

static const struct of_device_id apple6500spi_dt_ids[] = {
	{ .compatible = "applecai,apple6500spi"},
	{ /* sentinel */ }
};
/*
 * I2C init/probing/exit functions
 */
static int apple6500_spi_probe(struct spi_device *spi)
{
	struct apple6500 *m;
	
	m = apple6500_probe(&spi->dev,&apple6500_tf_spi);
	if (IS_ERR(m))
		return PTR_ERR(m);
	spi_set_drvdata(spi, m);
	
	return 0;
}

static int apple6500_spi_remove(struct spi_device *spi)
{
	struct apple6500 *m = spi_get_drvdata(spi);

	return apple6500_remove(m);
}


MODULE_DEVICE_TABLE(of, apple6500spi_dt_ids);

static struct spi_driver apple6500_driver = {
	.driver = {
		.name	= APPLE6500_DRV_NAME,
		.of_match_table = apple6500spi_dt_ids,
	},
	.probe		= apple6500_spi_probe,
	.remove   = apple6500_spi_remove,
};

module_spi_driver(apple6500_driver);

MODULE_AUTHOR("AppleCai");
MODULE_DESCRIPTION("APPLE6500 Acceler and Gyro Driver SPI");
MODULE_LICENSE("GPL");

